#include <list>
#include <map>
#include <string>
#include <fstream>
#include <iostream>

using namespace std;

#include "util.h"

enum tile_t { GENERIC, TILE, CUP, ENTITY, WALL};	//entity means anything that moves

class gameWorld;

class gameobj
{
	protected:
		gameobj(){};	
	public:
		gameWorld* worldPtr;	//world pointer
		tile_t objType;
		vec3 location;
		virtual void draw() {};
		virtual void update(float deltaTime) {};
		virtual void interact() {};
};

typedef list<gameobj*> level;	//a list of tiles is a level

class tile : public gameobj
{
	public: 
		tile();
		int tileID;		//tile ID :D
		int nVerts;
		float material[4];
		list<int> neighbors;
		list<vec3> coordinates;
		vec3 normal;

		void makeWall(list<gameobj*> &toAdd);
		vec3 getNormal();
		virtual void draw();
		//float interpolateHeight(vec3 height);
		void drawLines();
		void normalLines();
		bool pointIn(vec3 point); //we don't care about the y
		virtual void update(float deltaTime);

};

class wall : public gameobj
{
	public: 
		wall(vec3 c1, vec3 c2);
		vec3 normal;
		vec3 midPoint;
		list<vec3> coordinates;
		virtual void draw();
		virtual void update(float deltaTime);
		float D;
		float distance(vec3 point);
		bool bounce;
		float length;

};

class cup : public gameobj
{
	public:
		cup();
		
		void drawPole();
		virtual void draw();
		virtual void update(float deltaTime);
};

class ball : public gameobj
{
	public:
		ball();
		vec3 direction;		//velocity is a vector
		tile *currTile;
		float velocity;
		float radius;
		virtual void draw();
		virtual void update(float deltaTime);	
		virtual void interact();
		void bounce(vec3 norm);
};

class gameWorld
{
	public: 
		~gameWorld();	//dtor
		list<gameobj*> mObjList;	//all active objects (currently rendering)
		list<gameobj*> mAddList;
		list<gameobj*> mRemoveList;	

		ball* ballLoc;	//current ball location
		map<string, level> mLevelList;	//map of all level, string is filename

		void createLevel(char* fileName);
		void loadLevel(string fileName);	//clears mObjList, mRemoveList, and mAddList and insert
											//mLevelList[fileName] into mObjList.
		//void deleteLevel(string fileName);	//perma delete level and its pointers
		
		void addGameObject(gameobj &toAdd);
		void removeGameObject(gameobj &toRemove);

		void update(float deltatime);
		void draw();
		void gameWorld::camera(float &distance, const float Yangle, const float Xangle,  vec3 lookAt);
		void printObjList();
};